ggplot2: Basics

ggplot2: Das Paket


ggplot2 gehört zum tidyverse

# install.packages("tidyverse")
library(tidyverse)


… kann aber natürlich auch seperat geladen werden:

# install.packages("ggplot2")
library(ggplot2)

Komponenten

Daten



  x   y group size  shape
1 1 2.0     A    4 circle
2 2 3.0     A    5 circle
3 3 2.5     A    6 circle
4 4 4.0     A    7 circle
5 5 3.0     A    8 circle
6 2 1.0     B    3 circle

Aestetic mapping

Layers

Die Daten

Wir nutzen Daten von Gapminder.

Gapminder sammelt diverse Indikatoren aus allen Ländern weltweit, z.B. Lebenserwartung, GDP, CO2-Verbrauch und viele mehr.


Die Daten

Zuerst schauen wir uns nur eins der Jahre genauer an:

gapminder <- readRDS(here::here("data", "gapminder_dat.rds"))

gapminder_2019 <- gapminder %>%
  filter(time == 2019) %>%
  drop_na(gini, hapiscore_whr)

Gini-Koeffizient

  • 0 = perfekte Gleichheit (alle haben gleich viel)
  • 100 = perfekte Ungleichheit (eine Person hat alles)

Happiness-Score (Cantril-Leiter)

  • 0 = Schlechtestest mögliche Leben.
  • 100 = Bestmöglichstes Leben.

Start: ggplot()

ggplot()

1. Daten

ggplot(data = gapminder_2019)

2. Aesthetic mapping




Verknüpfen von Spalten im Datensatz mit visuellen Eigenschaften:

mapping =  aes()
Argument Aesthetic
x x-Achse
y y-Achse
color Farbe
fill Füllfarbe
shape Form
size Größe
alpha Transparenz
group Gruppe

Umfangreicherer Überblick über mögliche Aestethics.

Aesthetic mapping: Achsen

ggplot(
  data = gapminder_2019,
  mapping = aes(x = gini, y = hapiscore_whr)
)

3. Geometric Layers




Verschiedene Layers (geoms) werden übereinandergelegt:

geom_point() + 
geom_line() + 
...


Argument Aesthetic
geom_point() Punkte
geom_line() Linien
geom_histogram() Histogramm
geom_text() Text
geom_boxplot() Boxplot



Umfangreicherer Überblick über mögliche Geoms.

Layers: Punkte

ggplot(
  data = gapminder_2019,
  mapping = aes(x = gini, y = hapiscore_whr)
  ) +
  geom_point()



Das reicht schon, um einen eigenen ersten Plot zu erstellen. Nutzt die gapminder Daten und wählt zwei numerische Variablen aus.

str(gapminder)
tibble [59,371 × 45] (S3: tbl_df/tbl/data.frame)
 $ name                           : chr [1:59371] "Afghanistan" "Afghanistan" "Afghanistan" "Afghanistan" ...
 $ time                           : num [1:59371] 1976 1977 1978 1979 1980 ...
 $ part_time_employ_total         : num [1:59371] NA NA NA NA NA NA NA NA NA NA ...
 $ part_time_employ_fe            : num [1:59371] NA NA NA NA NA NA NA NA NA NA ...
 $ part_time_employ_ma            : num [1:59371] NA NA NA NA NA NA NA NA NA NA ...
 $ working_hours_week             : num [1:59371] NA NA NA NA NA NA NA NA NA NA ...
 $ country                        : chr [1:59371] "afg" "afg" "afg" "afg" ...
 $ c_demox_eiu                    : num [1:59371] NA NA NA NA NA NA NA NA NA NA ...
 $ co2_cons                       : num [1:59371] 1.91 2.3 2.09 2.17 1.64 ...
 $ co2_pcap_cons                  : num [1:59371] 0.153 0.181 0.162 0.167 0.132 0.15 0.163 0.201 0.231 0.294 ...
 $ co2_pcap_terr                  : num [1:59371] 0.159 0.187 0.166 0.171 0.14 0.176 0.206 0.252 0.274 0.331 ...
 $ co2_terr                       : num [1:59371] 1970046 2371161 2141546 2220567 1746716 ...
 $ cumulative_co2_emissions_tonnes: num [1:59371] 23199510 25500479 27592564 29758430 31402420 ...
 $ demox_eiu                      : num [1:59371] NA NA NA NA NA NA NA NA NA NA ...
 $ gdp_pcap                       : num [1:59371] 1833 1713 1812 1750 1761 ...
 $ gdp_pcap_21                    : num [1:59371] 2187 2054 2183 2119 2143 ...
 $ gini                           : num [1:59371] 33 33 33 33 32.9 ...
 $ gini_2100                      : num [1:59371] 33 33 33 33 32.9 ...
 $ hapiscore_whr                  : num [1:59371] NA NA NA NA NA NA NA NA NA NA ...
 $ lex                            : num [1:59371] 47.7 47.9 46.4 44.7 43.7 ...
 $ manuf_employ                   : num [1:59371] NA NA NA NA NA NA NA NA NA NA ...
 $ pop                            : num [1:59371] 13059851 13340756 13611441 13655567 13169311 ...
 $ u5pop                          : num [1:59371] 2426343 2486634 2530243 2544600 2520386 ...
 $ g77_and_oecd_countries         : chr [1:59371] "g77" "g77" "g77" "g77" ...
 $ income_groups                  : chr [1:59371] "low_income" "low_income" "low_income" "low_income" ...
 $ is--country                    : logi [1:59371] TRUE TRUE TRUE TRUE TRUE TRUE ...
 $ iso3166_1_alpha2               : chr [1:59371] "AF" "AF" "AF" "AF" ...
 $ unicode_region_subtag          : chr [1:59371] "AF" "AF" "AF" "AF" ...
 $ iso3166_1_alpha3               : chr [1:59371] "AFG" "AFG" "AFG" "AFG" ...
 $ iso3166_1_numeric              : num [1:59371] 4 4 4 4 4 4 4 4 4 4 ...
 $ iso3166_2                      : chr [1:59371] NA NA NA NA ...
 $ landlocked                     : chr [1:59371] "landlocked" "landlocked" "landlocked" "landlocked" ...
 $ latitude                       : num [1:59371] 33 33 33 33 33 33 33 33 33 33 ...
 $ longitude                      : num [1:59371] 66 66 66 66 66 66 66 66 66 66 ...
 $ main_religion_2008             : chr [1:59371] "muslim" "muslim" "muslim" "muslim" ...
 $ un_state                       : logi [1:59371] TRUE TRUE TRUE TRUE TRUE TRUE ...
 $ world_4region                  : chr [1:59371] "asia" "asia" "asia" "asia" ...
 $ world_6region                  : chr [1:59371] "south_asia" "south_asia" "south_asia" "south_asia" ...
 $ unicef_region                  : chr [1:59371] "sa" "sa" "sa" "sa" ...
 $ income_3groups                 : chr [1:59371] "low_income" "low_income" "low_income" "low_income" ...
 $ un_sdg_region                  : chr [1:59371] "un_central_and_southern_asia" "un_central_and_southern_asia" "un_central_and_southern_asia" "un_central_and_southern_asia" ...
 $ un_sdg_ldc                     : chr [1:59371] "un_least_developed" "un_least_developed" "un_least_developed" "un_least_developed" ...
 $ unhcr_region                   : chr [1:59371] "unhcr_asia_pacific" "unhcr_asia_pacific" "unhcr_asia_pacific" "unhcr_asia_pacific" ...
 $ west_and_rest                  : chr [1:59371] "rest" "rest" "rest" "rest" ...
 $ global                         : chr [1:59371] NA NA NA NA ...
  • Jahre: time
  • Teilzeitbeschäftigung: part_time_employ_...
  • Gini-Index: gini
  • Happiness-Score: hapiscore_whr
  • Co2-Ausstoß pro Kopf: co2_pcap
  • GDP pro Kopf (inflation-adjusted): gdp_pcap

Wenn eine eurer Variablen nicht time ist, wählt euch am besten ein Jahr aus, dass ihr euch anschaut.

Code
gapminder_2019 <- gapminder %>%
  filter(time == 2019) %>%
  drop_na(gini, hapiscore_whr)

Erstellt daraus einen Scatterplot. Gibt es einen Zusammenhang zwischen euren Variablen?

ggplot(
  data = gapminder_2019,
  mapping = aes(
    x = gini,
    y = hapiscore_whr
  )
) +
  geom_point()

Länder mit niedrigerem Gini-Index haben tendenziell einen höheren Happiness-Score.

Mehr Aesthetics!

ggplot(
  data = gapminder_2019,
  mapping = aes(
    x = gini, y = hapiscore_whr,
    color = world_4region
  )
) +
  geom_point()

Mehr Layers!

ggplot(
  data = gapminder_2019,
  mapping = aes(x = gini, y = hapiscore_whr, color = world_4region)
) +
  geom_point() +
  geom_smooth()


Probiert aus, wo in den ggplot-layers man die Farbe ändern kann (es gibt 3 verschiedene Möglichkeiten, die sich alle unterschiedlich auf den Plot auswirken).
Ändert dafür unseren bisherigen Plot so, dass nur die Punkte farbig sind.
Die Linie von geom_smooth() soll einfarbig werden.

ggplot(
  data = gapminder_2019,
  mapping = aes(x = gini, y = hapiscore_whr, color = world_4region)
) +
  geom_point() +
  geom_smooth()
ggplot(
  data = gapminder_2019,
  mapping = aes(x = gini, y = hapiscore_whr)
) +
  geom_point(aes(color = world_4region)) +
  geom_smooth()

Wir ändern dafür die Aesthetics von global zu lokal, indem wir die color-Aesthetic nur in geom_point() definieren.

Aestetics als Mapping oder Setting

Für alle Layer

ggplot(
  data = gapminder_2019,
  mapping = aes(
    x = gdp_pcap,
    y = hapiscore_whr,
    color = world_4region)
) +
  geom_point() +
  geom_smooth()

Für spezifische Layer

ggplot(
  data = gapminder_2019,
  mapping = aes(
    x = gini,
    y = hapiscore_whr
  )
) +
  geom_point(aes(color = world_4region)) +
  geom_smooth()

Als Setting

ggplot(
  data = gapminder_2019,
  mapping = aes(
    x = gini,
    y = hapiscore_whr
  )
) +
  geom_point(color = "#F4BA02") +
  geom_smooth()

Labels

ggplot(
  data = gapminder_2019,
  mapping = aes(
    x = gini,
    y = hapiscore_whr
  )
) +
  geom_point(aes(color = world_4region)) +
  geom_smooth() +
  labs(
    title = "Ungleichheit = Un-Happiness?",
    subtitle = "Gini-Koeffizient und Happiness-Score in verschiedenen Ländern 2019",
    x = "Gini-Index",
    y = "Happiness-Score",
  )

Style deinen Plot: Themes

ggplot(
  data = gapminder_2019,
  mapping = aes(
    x = gini,
    y = hapiscore_whr
  )
) +
  geom_point(aes(color = world_4region)) +
  geom_smooth() +
  labs(
    title = "Ungleichheit = Un-Happiness?",
    subtitle = "Gini-Koeffizient und Happiness-Score in verschiedenen Ländern 2019",
    x = "Gini-Index",
    y = "Happiness-Score",
  ) +
  theme_bw()

Eine Übersicht über Themes findet sich hier.

🏋 Übung

  1. Wir losen Gruppen aus. Stellt in den Gruppen kurz eure Scatterplots aus der vorherigen Übung vor. 5 min
  2. Erstellt in Einzelarbeit den euch zugewiesenen Plot-Typen. Nutzt dafür die Variablen, die ihr am interessantesten findet (entweder aus den bisherigen Übungen, oder aus dem Gruppengespräch). 30 min
  • Lineplot: 1 numerische, 1 kategoriale und die Jahres-Variable
  • Barplot: 1 kategoriale und 1 numerische Variable
  • Densityplot: 1 numerische und 1 kategoriale Variable
  • Boxplot: 1 numerische und 1 kategoriale Variable
  • Histogram: 1 numerische Variable + eine kategoriale Variable

Als kategoriale Variable bietet sich z.B. world_6region an.

Nutzt die bisherigen Code-Blocks, R-interne Hilfe, Google und KI. Falls ihr eine bestimmte Vision habt, aber nicht wisst wie ihr z.B. die Daten umformt, sagt bitte direkt Bescheid, damit wir helfen können!

🏋 Übung

  1. Gruppenarbeit: Zusammenfinden in den Gruppen, um einen finalen Plot zu küren/erstellen (15 min). Dieser kann Elemente aus verschiedenen Plots enthalten. Ihr könnt auch euren Plot fortführen, wenn ihr den interessanter findet, oder um Inspo von den anderen ergänzen. An diesem finalen Plot könnt ihr dann im Laufe des Workshops weiterarbeiten.
  2. Kurze Vorstellung im Plenum. 10 min
library(tidyverse)

gapminder <- readRDS(here::here("data", "gapminder_dat.rds")) 

gapminder_vars <- gapminder %>%
  select(name, time, part_time_employ_total, part_time_employ_fe, part_time_employ_ma, working_hours_week, world_6region, income_3groups) %>%
  drop_na(part_time_employ_total, working_hours_week)

gapminder_vars_de <- gapminder_vars %>% filter(name == "Germany")
line_plot <- ggplot(data = gapminder_vars_de,
       mapping = aes(x = time, y = working_hours_week)) +
  geom_line() +
  labs(
    title = "Arbeitsstunden pro Woche in Deutschland",
    x = "Jahr",
    y = "Arbeitsstunden pro Woche",
    color = "Land"
  ) +
  theme_minimal()

line_plot

bar_plot <- ggplot(data = gapminder_vars, 
       mapping = aes(x = time, y = part_time_employ_total)) +
  geom_bar(stat = "identity") +
  theme_minimal() +
  labs(
    title = "Teilzeitbeschäftigungsrate in Deutschland",
    x = "Jahr",
    y = "Teilzeitbeschäftigungsrate (%)"
  )

bar_plot

gapminder_vars_2019 <- gapminder_vars %>% filter(time == 2019)

ggplot(data = gapminder_vars_2019, 
       aes(x = working_hours_week, fill = income_3groups)) +
  geom_density(alpha = 0.4) +
  theme_minimal() +
  labs(
    title = "Arbeitsstunden pro Woche",
    subtitle = "In Ländern aus verschiedenen Einkommensgruppen",
    x = "Arbeitsstunden pro Woche",
    y = "Dichte",
    fill = "Einkommensgruppe"
  )

gapminder_vars_long <- gapminder_vars %>%
  pivot_longer(cols = contains("part_time_employ"),
               names_to = "part_time_type",
               values_to = "part_time_employ_rate") %>%
  mutate(part_time_type = str_replace(part_time_type, "part_time_employ_", ""))

gapminder_vars_2019 <- gapminder_vars_long %>% filter(time == 2019)

ggplot(data = gapminder_vars_2019, 
       mapping = aes(x = world_6region, y = part_time_employ_rate, fill = part_time_type)) +
  geom_boxplot() +
  theme_minimal() +
  labs(
    title = "Teilzeitbeschäftigungsrate in verschiedenen Kontinenten",
    subtitle = "Im Jahr 2019",
    x = "",
    y = "Teilzeitbeschäftigungsrate (%)"
  )

gapminder_vars_2019 <- gapminder_vars %>% filter(time == 2019)

ggplot(data = gapminder_vars_2019, 
       aes(x = working_hours_week, fill = income_3groups)) +
  geom_histogram(binwidth = 3 ) +
  theme_minimal() +
  labs(
    title = "Arbeitsstunden pro Woche",
    subtitle = "In Ländern aus verschiedenen Einkommensgruppen",
    x = "Arbeitsstunden pro Woche",
    y = "Dichte",
    fill = "Einkommensgruppe"
  )

library(patchwork)

line_plot +
  bar_plot +
  plot_layout(ncol = 1)